package openai

import (
	"chatgpt/helper"
	"chatgpt/helper/code"
	"chatgpt/logq"
	"chatgpt/plugin/found"
	"chatgpt/plugin/httpsrv"
	"fmt"
	"github.com/gin-gonic/gin"
	gogpt "github.com/sashabaranov/go-openai"
	"io"
	"net/http"
	url2 "net/url"
	"strings"
)

type Request struct {
	Text  string `json:"text"`
	Model string
	User  *User
	Stop  []string
}

type User struct {
	Role string
	Name string
	UID  string
}

type Response struct {
	MsgCode code.CODENO
	Text    string
	Tokens  int
}

func (self *Response) Echo(ctx *gin.Context) {
	ctx.JSON(http.StatusOK, &helper.Response{MsgCode: int(self.MsgCode), Data: self.Text, Desc: self.MsgCode.String(), Tokens: self.Tokens})
}

type ResponseCompletion struct {
	resp    gogpt.CompletionResponse
	MsgCode code.CODENO
}

type RequestImage struct {
	Text string `json:"text"`
	N    int
	Size string
}
type ResponseImage struct {
	resp    gogpt.ImageResponse
	MsgCode code.CODENO
}

type ResponseDesc struct {
	MsgCode code.CODENO
	Data    interface{}
	Desc    string
	Tokens  int
}

type ChatResponse struct {
	resp    gogpt.ChatCompletionResponse
	MsgCode code.CODENO
}

// function

func RemoteAiGet(qargs ...string) (code.CODENO, string) {
	cnf := helper.Config().Sub("Server")
	addr_url := cnf.Sub("ChatGPT").GetString("RmmoteAiUrl")
	res := ResponseDesc{}
	var q, model, size = "", "", ""
	if len(qargs) >= 1 {
		q = qargs[0]
	}
	if len(qargs) >= 2 {
		model = qargs[1]
	}
	if len(qargs) >= 3 {
		size = qargs[2]
	}
	param := fmt.Sprintf("?api_key=%v&q=%v&model=%v&size=%v", strings.ReplaceAll(cnf.GetString("AuthToken"), "#", "%23"), url2.QueryEscape(q), model, size)
	url := cnf.Sub("ChatGPT").GetString("RemoteAi") + addr_url + param
	//dddd := "http://localhost:18060/question/origin?api_key=API-TD.DFD%23$D$GDL-2D%23dfCDDG@2*DFWMBV%23DFEDF&q=who%20are%20you&model=&size=512x512"
	err := httpsrv.Get((url), &res)

	if err != nil {
		logq.Error("Init.RegisterSrv err: ", err)
		return code.SERVER_ERR, ""
	}
	if res.MsgCode != code.SUCCESS {
		return res.MsgCode, ""
	}
	data := res.Data
	return res.MsgCode, data.(string)
}

func RemoteApi(url_path string, q string, m map[string]string) (code.CODENO, *helper.ResponseDesc) {
	cnf := helper.Config().Sub("Server")
	//addr_url := cnf.GetString("RmmoteAiUrl")
	res := &helper.ResponseDesc{}
	//pa1 := ""
	//if len(m) > 0 {
	//	for k, v := range m {
	//		pa1 += "&" + k + "=" + v
	//	}
	//}
	mm := helper.ConvMapStringToMapAny(m)
	mm["q"] = q
	param := fmt.Sprintf("?api_key=%v", strings.ReplaceAll(cnf.GetString("AuthToken"), "#", "%23"))
	url := cnf.Sub("ChatGPT").GetString("RemoteAi") + url_path + param
	//dddd := "http://localhost:18060/question/origin?api_key=API-TD.DFD%23$D$GDL-2D%23dfCDDG@2*DFWMBV%23DFEDF&q=who%20are%20you&model=&size=512x512"
	err := httpsrv.Post((url), mm, &res)

	if err != nil {
		logq.Error("Init.RegisterSrv err: ", err)
		return code.SERVER_ERR, res
	}
	if res.MsgCode != code.SUCCESS {
		return res.MsgCode, res
	}
	//data := res.Data
	return res.MsgCode, res
}

func RemoteStream(w http.ResponseWriter, url_path string, m map[string]any, dest io.Writer) (code.CODENO, *helper.ResponseDesc) {
	cnf := helper.Config().Sub("Server")
	//addr_url := cnf.GetString("RmmoteAiUrl")

	res, resok := dest.(*helper.ResponseDesc)

	param := fmt.Sprintf("?api_key=%v", strings.ReplaceAll(cnf.GetString("AuthToken"), "#", "%23"))
	url := cnf.Sub("ChatGPT").GetString("RemoteAi") + url_path + param
	//dddd := "http://localhost:18060/question/origin?api_key=API-TD.DFD%23$D$GDL-2D%23dfCDDG@2*DFWMBV%23DFEDF&q=who%20are%20you&model=&size=512x512"
	err := httpsrv.PostStream(w, url, m, res)

	if err != nil {
		logq.Error("Init.RegisterSrv err: ", err)
		return code.SERVER_ERR, res
	}
	if !resok {
		return code.SUCCESS, &helper.ResponseDesc{
			MsgCode: code.SUCCESS,
		}
	}
	if res.MsgCode != code.SUCCESS {
		return res.MsgCode, res
	}
	//data := res.Data
	return res.MsgCode, res
}

// @return string prompt
// @return bool  是否使用了 索引
func CustomQuestion(prompt string) (string, bool) {
	data := found.Data{}
	err := found.Default.Query(&data, prompt, map[string]any{})
	if err != nil || len(data.Documents) == 0 {
		return prompt, false
	}
	result := ""
	for _, item := range data.Documents {
		result += item.Document.Prompt + "\n" + item.Document.Completion + "\n\n"
	}
	result = result[:len(result)-2]
	return "system:" + OPENAI_PROMPT_PRIFIX + "\n\n" + result + "\nuser:" + prompt, true
}
